package com.accesshollywood.grfxOrdering.Dialogs;

import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.util.EnumSet;

import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.SpringLayout;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.VerticalLayout;

import com.accesshollywood.advDatatypes.BoundedInt;
import com.accesshollywood.components.SpringUtilities;
import com.accesshollywood.grfxOrdering.OrderMainGUI;
import com.accesshollywood.prefs.Prefs;
import com.accesshollywood.trace.Trace;

public class PrefsDialog extends AbstractCustomDialog {

	private JPanel	contentPanel;

	public PrefsDialog(Window w, ModalityType modality) {
		super(w, modality);
		createDialog();
	}

	public void createDialog() {
		setBounds(100, 100, 270, 400);
		contentPanel = (JPanel) getContentPane();
		contentPanel.setLayout(new VerticalLayout());

		JTabbedPane tabs = new JTabbedPane();

		Class<?>[] innerClasses = Prefs.class.getDeclaredClasses();

		for (Class currClass : innerClasses) {
			String name = currClass.getSimpleName();

			JPanel newPanel = new JPanel();
			newPanel.setLayout(new VerticalLayout(-5));

			tabs.setPreferredSize(new Dimension(260, 350));
			tabs.setMinimumSize(new Dimension(260, 350));
			tabs.setMaximumSize(new Dimension(260, 350));

			JScrollPane scroller = new JScrollPane(newPanel);
			scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

			Field[] fields = currClass.getFields();

			int count = 0;
			for (Field currField : fields) {
				if (currField.getType().equals(BoundedInt.class)) {
					newPanel.add(createInt(currClass, currField));
				} else if (currField.getType().equals(EnumSet.class)) {
					JPanel subPanel = createEnumSet(currClass, currField);
					if (subPanel != null) {
						newPanel.add(subPanel);
					}
				}
				count++;
			}

			tabs.add(name, scroller);// newPanel);
		}

		add(tabs);

		this.setVisible(true);
	}

	private JPanel createEnumSet(final Class currClass, final Field currField) {
		Class[] enumClasses = currClass.getClasses();

		Object[] prefSettings = null;
		Class enumClass = null;
		for (int i = 0; i < enumClasses.length; i++) {
			if (enumClasses[i].isEnum()) {
				prefSettings = enumClasses[i].getDeclaredFields();
				enumClass = enumClasses[i];
				break;
			}
		}
		JPanel fieldPanel = null;
		if (enumClass != null) {
			fieldPanel = new JPanel();

			JPanel checkPanel = new JPanel();
			checkPanel.setBorder(new TitledBorder(currField.getName()));
			checkPanel.setLayout(new HorizontalLayout());
			checkPanel.setPreferredSize(new Dimension(200, 40));
			checkPanel.setMinimumSize(new Dimension(200, 40));
			checkPanel.setMaximumSize(new Dimension(200, 40));

			try {
				EnumSet actualSetting = (EnumSet) currField.get(currClass);

				for (int i = 0; i < prefSettings.length - 1; i++) {
					Field currEnumField = (Field) prefSettings[i];
					Enum currEnum = (Enum) currEnumField.get(enumClass);

					JCheckBox check = new JCheckBox(currEnumField.getName());

					check.addActionListener(new EnumSetCheckActionListener(currClass, currField, currEnumField));

					if (actualSetting.contains(currEnum)) {
						check.setSelected(true);
					}

					checkPanel.add(check);
				}

			} catch (Exception e) {
				e.printStackTrace();
			}

			fieldPanel.add(checkPanel);
		}
		return fieldPanel;
	}

	private class EnumSetCheckActionListener implements ActionListener {
		Class	currClass		= null;
		Field	currField		= null;
		Field	currEnumField	= null;

		public EnumSetCheckActionListener(Class currClass, Field currField, Field currEnumField) {
			this.currClass = currClass;
			this.currField = currField;
			this.currEnumField = currEnumField;
		}

		@Override
		public void actionPerformed(ActionEvent arg0) {
			Trace.info(Prefs.Notifications.orderAssigned.toString());
			Trace.info(Prefs.Notifications.orderUnassigned.toString());
			Trace.info(Prefs.Notifications.orderModified.toString());
			Trace.info(Prefs.Notifications.textEdited.toString());
			
			try {
				Class[] enumClasses = currClass.getClasses();

				Object[] prefSettings = null;
				Class enumClass = null;
				for (int i = 0; i < enumClasses.length; i++) {
					if (enumClasses[i].isEnum()) {
						prefSettings = enumClasses[i].getDeclaredFields();
						enumClass = enumClasses[i];
						break;
					}
				}
				
				Trace.info(Prefs.Notifications.orderAssigned.toString());
				Trace.info(Prefs.Notifications.orderUnassigned.toString());
				Trace.info(Prefs.Notifications.orderModified.toString());
				Trace.info(Prefs.Notifications.textEdited.toString());
				
				if (enumClass != null) {
					Trace.info(currField.get(Prefs.class).toString());
					EnumSet currPref = (EnumSet) currField.get(Prefs.class);

					Enum currEnum = (Enum) currEnumField.get(Prefs.class);

					JCheckBox check = (JCheckBox) arg0.getSource();

					Trace.info(Prefs.Notifications.orderAssigned.toString());
					Trace.info(Prefs.Notifications.orderUnassigned.toString());
					Trace.info(Prefs.Notifications.orderModified.toString());
					Trace.info(Prefs.Notifications.textEdited.toString());
					
					if (check.isSelected()) {
						currPref.add(currEnum);

						Trace.info(Prefs.Notifications.orderAssigned.toString());
						Trace.info(Prefs.Notifications.orderUnassigned.toString());
						Trace.info(Prefs.Notifications.orderModified.toString());
						Trace.info(Prefs.Notifications.textEdited.toString());
					} else {
						currPref.remove(currEnum);

						Trace.info(Prefs.Notifications.orderAssigned.toString());
						Trace.info(Prefs.Notifications.orderUnassigned.toString());
						Trace.info(Prefs.Notifications.orderModified.toString());
						Trace.info(Prefs.Notifications.textEdited.toString());
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

			Trace.info(Prefs.Notifications.orderAssigned.toString());
			Trace.info(Prefs.Notifications.orderUnassigned.toString());
			Trace.info(Prefs.Notifications.orderModified.toString());
			Trace.info(Prefs.Notifications.textEdited.toString());
		}
	}

	private String getBinaryVector(EnumSet e) {
		Class<?> c = e.getClass();
		try {
			Field elements = c.getDeclaredField("elements");
			elements.setAccessible(true);
			return Long.toBinaryString(elements.getLong(e));
		} catch (Exception x) {
			x.printStackTrace();
		}
		return "";
	}

	private JPanel createInt(final Class currClass, final Field currField) {
		JPanel fieldPanel = new JPanel();
		fieldPanel.setLayout(new SpringLayout());

		JLabel label = new JLabel(currField.getName());

		JSlider control = new JSlider();

		try {
			BoundedInt currValue = (BoundedInt) currField.get(currField);
			control.setMinimum(currValue.getMin());
			control.setMaximum(currValue.getMax());
			control.setValue(currValue.get());
		} catch (Exception e) {
			e.printStackTrace();
		}

		control.setPreferredSize(new Dimension(100, 20));
		control.setMaximumSize(new Dimension(100, 20));
		control.setMinimumSize(new Dimension(100, 20));

		final JLabel value = new JLabel(control.getValue() + "");

		fieldPanel.add(label);
		fieldPanel.add(control);
		fieldPanel.add(value);

		control.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent arg0) {
				JSlider source = (JSlider) arg0.getSource();
				try {
					value.setText(((JSlider) arg0.getSource()).getValue() + "");
					BoundedInt currPref = (BoundedInt) currField.get(currField);
					currPref.set(((JSlider) arg0.getSource()).getValue());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (!source.getValueIsAdjusting()) {
					OrderMainGUI.refresh(false);
				}
			}
		});

		SpringUtilities.makeGrid(fieldPanel, 1, 3, 5, 5, 5, 0);

		return fieldPanel;
	}
}
